home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
ASME's Mechanical Engine…ing Toolkit 1997 December
/
ASME's Mechanical Engineering Toolkit 1997 December.iso
/
edu_comp
/
tpnovell.lzh
/
CIS.PAS
Wrap
Pascal/Delphi Source File
|
1987-10-02
|
20KB
|
530 lines
{ This is my Novell Toolbox for printing, file and record locking, }
{ logical locks, and semaphores. }
{ If you use these routines in your software, and find them of value, }
{ please send a contribution of $15 to $50 to me for funding of additional }
{ toolboxes. If you find these routines useful and use them in a commercial }
{ application, no royalties are requested. If you do profit from these }
{ routines, please consider a larger donation. }
{ Also please send your ideas for future toolboxes. The current plans }
{ include Novell spooling print functions, an IPX concentrator, and of }
{ course, the elusive Novell B+ Tree routines, compatible with Borland's }
{ database toolbox, but completely networkable. I know you want these, and }
{ if I find time, I'll finish them. Your contributions go a long way towards }
{ finding the time to work on this stuff. }
{ Telephone support is available for my routines at Micro Networks of America }
{ in Farmington, CT (203) 678-7400. Our current consulting rate must be }
{ charged if I support you from the office, via the phone. Other support is }
{ available for free via compuserve (Borland SIG) or via mail at home. }
{ The address for contributions and support questions is: }
{ Scott A. Lewis
36 Maythorpe Drive
Windsor, CT 06095
On Compuserve, send mail to 76515,135 via Easyplex or Borland's SIG.
}
{ The future toolboxes complete descriptions are as follows:
IPX concentrator: A PC to PC communications toolbox using Novell's
IPX internetwork communications. The primary
application will be sharing a host communication
line, however, a print or modem server might be
easily implemented.
Novell print spooling: A demo program that is a simple popup spool
utility. Similar to Hotprint, but with less
complexity. The toolbox will include functions
for all of Novell's printing function calls.
Novell B+ Trees: I needn't explain this one, especially if you have
followed my LAN threads on Compuserve (Borland SIG).
I really have been working on this one, but it is big,
tough to document, and difficult to make as fast as the
original. I'll get one of these days.
Send your ideas for future toolboxes !
}
TYPE
Str80 = STRING[80];
RecLogType = STRING[100];
Str6 = STRING[6];
BigStr = STRING[255];
Reg_Type = RECORD
CASE Byte OF
0 : (AX, BX, CX, DX, BP, SI, DI, DS, ES, Flags : Integer);
1 : (AL, AH, BL, BH, CL, CH, DL, DH : Byte);
END;
Request_Type = ARRAY[1..7] OF Byte;
Reply_Type = ARRAY[1..90] OF Char;
VAR
Regs : Reg_Type;
Request_Buff : Request_Type;
Reply_Buff : Reply_Type;
I, J : Integer;
FUNCTION Open_Semaphore(Sem : BigStr;
InitVal : Integer;
VAR SemHandle1 : Integer;
VAR SemHandle2 : Integer;
VAR Num_Using : Integer) : Boolean;
{ Semaphores are used for exclusion when record locking is not appropriate }
{ The value is set the first time the semaphore is opened, thereafter you }
{ must use wait semaphore or signal semaphore to change the value }
BEGIN
WITH Regs DO
BEGIN
IF (Sem[0] > #127) OR (InitVal < 0) OR (InitVal > 127) THEN
BEGIN { Semaphore must not exceed 127 chars }
Open_Semaphore := False; { InitVal must be between 0 and 127 }
Exit;
END;
AH := $C5; { Semaphore function }
AL := $0; { Sub-Function 0 = open }
DS := Seg(Sem); { DS:DX points to name }
DX := Ofs(Sem); { Byte 0 = length 0..127 }
CL := InitVal; { Initial Value 0..127 }
MsDos(Regs); { Give it to Int 21h }
Num_Using := BL; { Number of users using this semaphore }
Open_Semaphore := (AL = 0); { OK if AL comes back as 0 }
SemHandle1 := CX; { CX:DX holds the semaphore handle }
SemHandle2 := DX;
END; { with Regs do }
END; {Function Open_Semaphore }
FUNCTION Examine_Semaphore(SemHandle1, SemHandle2 : Integer;
VAR Value : Integer;
VAR Num_Using : Integer) : Boolean;
{ The semaphore value that comes back in CL is the count from the open call }
{ DL represents the current open count - the open count is incremented }
{ anytime a station opens the semaphore this can be used for controlling }
{ the number of users using your software }
BEGIN
WITH Regs DO
BEGIN
AH := $C5; { Semaphore function call }
AL := 1; { Sub-Function 1 = examine }
CX := SemHandle1;
DX := SemHandle2;
MsDos(Regs); { Give it to DOS }
Value := CX; { Semaphore value in CX }
Num_Using := DL; { Number using this semaphore }
Examine_Semaphore := (AL = 0); { AL = 0 means OK }
END;
END; { function Examine_Semaphore }
FUNCTION Wait_Semaphore(SemHandle1, SemHandle2 : Integer;
Wait_Time : Integer) : Boolean;
{ Decrement the semaphore value and wait if it is negative. If negative, }
{ the workstation will wait until it becomes non-negative or until a }
{ timeout occurs. }
BEGIN
WITH Regs DO
BEGIN
AH := $C5; { Semaphore function call }
AL := 2; { Sub-Function 2 = wait }
BP := Wait_Time; { In 1/18 seconds, 0 = No wait }
CX := SemHandle1;
DX := SemHandle2;
MsDos(Regs); { Give it to DOS }
Wait_Semaphore := (AL = 0); { AL = 0 means OK, else timeout or
Invalid handle }
END;
END; { function Wait_Semaphore }
FUNCTION Signal_Semaphore(SemHandle1, SemHandle2 : Integer) : Boolean;
{ Increment the semaphore value and release if waiting. If any stations }
{ are waiting, the station that has been waiting the longest will be }
{ signalled to proceed }
BEGIN
WITH Regs DO
BEGIN
AH := $C5; { Semaphore function call }
AL := 3; { Sub-Function 3 = signal }
CX := SemHandle1;
DX := SemHandle2;
MsDos(Regs); { Give it to DOS }
Signal_Semaphore := (AL = 0); { AL = 0 means OK, else overflow ( value > 128 ) }
{ or Invalid handle }
END;
END; { function Signal_Semaphore }
FUNCTION Close_Semaphore(SemHandle1, SemHandle2 : Integer) : Boolean;
{ Decrement the open count of a semaphore. When the open count goes }
{ to zero, the semaphore is destroyed. }
BEGIN
WITH Regs DO
BEGIN
AH := $C5; { Semaphore function call }
AL := 4; { Sub-Function 4 = close }
CX := SemHandle1;
DX := SemHandle2;
MsDos(Regs); { Give it to DOS }
Close_Semaphore := (AL = 0); { AL = 0 means OK, else Invalid handle }
END;
END; { function Close_Semaphore }
FUNCTION Set_Lock_Mode : boolean;
{ Note that if other applications are running that were written for Netware }
{ 4.61 or older, this should be set back to old compatibility mode before we }
{ exit. This can be done by using this call with AL = 00h }
BEGIN
WITH Regs DO
BEGIN
AH := $C6; { Lock mode function }
AL := 1; { We want extended mode }
END;
END;
(* THE FOLLOWING PROCEDURES ARE FOR LOGGING AND LOCKING/RELEASING FILE SETS *)
(* File locking by set can be very effective in avoiding deadly embrace *)
FUNCTION Lock_File_Set(Mode : Byte; Timeout : Byte) : Boolean;
{ Lock a set of files that were logged by function $EB log asciiz file }
BEGIN
WITH Regs DO
BEGIN
AH := $CB; { Lock File Set Function }
DL := Mode; { 0 = No Wait, 1 = wait }
BP := Timeout; { in 1/18 seconds ... 0 = No Wait }
MsDos(Regs); { Give it to DOS }
Lock_File_Set := (AL = 0); { Al = 0 means OK FF = Fail FE = Timeout }
END;
END; { function Lock_File_Set(Mode : Byte; Timeout : Byte) }
Procedure Release_File_Set;
{ Release lock on set of files in logged table, files remain logged }
{ These files remain open but cannot be accessed without an error }
{ To reuse them, send another lock file set }
BEGIN
WITH Regs DO
BEGIN
AH := $CD; { Release file set function }
MsDos(Regs);
END;
END; { function Release_File_Set }
FUNCTION Clear_File_Set : Boolean;
{ Unlock and UnLog the entire personal file set (all files are closed) }
BEGIN
WITH Regs DO
BEGIN
AH := $CF; { Release File Set Function }
MsDos(Regs);
Clear_File_Set := (AL = 0); { Al = 0 means OK }
END;
END; { function Clear_File_Set }
FUNCTION Log_File(FName : Str80; Mode : Byte; Timeout : Byte) : Boolean;
VAR
Asciiz : STRING[80];
{ This function allows a station to log files fro later personal use }
{ After the desired files are logged, function CBh can be used to lock }
{ the entire set of files }
BEGIN
WITH Regs DO
BEGIN
AH := $EB; { Log Asciiz string function }
AL := Mode; { 0 = Log Only, 1 Log and Lock }
BP := Timeout; { in 1/18 seconds, 0 = No wait }
Asciiz := FName+#0; { Terminate with a nul for asciiz }
DS := Seg(Asciiz);
DX := Ofs(Asciiz[1]);
MsDos(Regs);
Log_File := (AL = 0);
END;
END; { function Log_File }
FUNCTION Release_File(FName : Str80) : boolean;
VAR
Asciiz : STRING[80];
{ Release file lock, but keep logged in the table }
BEGIN
WITH Regs DO
BEGIN
AH := $EC; { Release file call }
Asciiz := FName+#0; { null terminate }
DS := Seg(Asciiz);
DX := Ofs(Asciiz[1]);
MsDos(Regs);
END;
END; { function Release_File }
FUNCTION Clear_File(FName : Str80) : boolean;
VAR
Asciiz : STRING[80];
{ Release a file from the file log table, unlock the file if it is locked }
BEGIN
WITH Regs DO
BEGIN
AH := $ED;
Asciiz := FName+#0;
DS := Seg(Asciiz);
DX := Ofs(Asciiz[1]);
MsDos(Regs);
Clear_File := (AL = 0); { Al = 0 means OK }
END;
END; { Function Clear_File }
(* THE FOLLOWING FUNCTIONS ARE FOR LOGICAL LOCKING OPERATIONS *)
(* Logical locks work only if all software accessing the files use the *)
(* same logical synchronization scheme. Logical locks are much easier *)
(* and faster to implement than physical locks. *)
FUNCTION Begin_Logical_Locking(Mode, Timeout : Integer) : Boolean;
{ Call this when you are about to start the read modify update cycle on an }
{ open shareable file or set of files. The mode can be zero or one for }
{ No wait or wait, if wait is chosen, the timeout value is set in 1/18th }
{ seconds. When the shell receives this call, it sends a request to the }
{ server to lock all shareable files that the workstation has opened. This }
{ only works on file flagged as shareable and is only effective if all }
{ stations that are acessing the files use this method }
BEGIN
WITH Regs DO
BEGIN
AH := $C8; { Begin Logical File Locking Function }
DL := Mode; { 0 = No wait, 1 = Wait }
IF Mode = 1 THEN
BP := Timeout; { timeout in 1/18th seconds -- 0 = No wait }
MsDos(Regs);
Begin_Logical_Locking := (AL = 0); { AL=FFh if fail, AL=FEh if
timeout }
END;
END; { function Begin_Logical_Locking }
FUNCTION End_Logical_Locking : Boolean;
{ This call will indicate that the read modify update cycle is complete }
{ and unlock the logical locks previously placed by Begin_Logical_Locking }
BEGIN
WITH Regs DO
BEGIN
AH := $C9;
MsDos(Regs);
End_Logical_Locking := (AL = 0);
END;
END; { End_Logical_Locking }
FUNCTION Log_Logical_Record(Flg, Timeout : Integer; VAR RecName : RecLogType) : Boolean;
{ This function will log the specified record string in the record log table }
{ of the requesting station. The record format for this string is as follows }
{ byte value }
{ 0 length }
{ 1..100 data }
BEGIN
WITH Regs DO
BEGIN
AH := $D0;
AL := Flg; { If bit zero is set, lock as well as log }
{ If bit one is set, non-exclusive lock( valid only if }
{ bit zero is set. }
DS := Seg(RecName);
DX := Ofs(RecName);
BP := Timeout; { In 1/18th seconds (use only with lock bit set }
MsDos(Regs);
Log_Logical_Record := (AL = 0); { Possible errors in AL are }
{ AL=FFh fail }
{ AL=FEh timeout }
{ AL=96h No dynamic memory for file }
END;
END; { Log_Logical_Record }
FUNCTION Lock_Logical_RecSet(Timeout : Integer) : Boolean;
{ Call this to lock all records logged with Log_Logical_Record }
BEGIN
WITH Regs DO
BEGIN
AH := $D1;
BP := Timeout; { In 1/18th seconds, 0 = No wait }
MsDos(Regs);
Lock_Logical_RecSet := (AL = 0); { AL=FF - fail, AL=FE - timeout }
END;
END; { Lock_Logical_RecSet }
FUNCTION Release_Logical_Rec(VAR RecName : RecLogType) : Boolean;
{ Call this to release a logical record lock without removing the rec }
{ from the table }
BEGIN
WITH Regs DO
BEGIN
AH := $D2;
DS := Seg(RecName);
DX := Ofs(RecName);
MsDos(RecName);
Release_Logical_Rec := (AL = 0);
END;
END; { Release_Logical_Rec }
FUNCTION Release_Logical_RecSet : Boolean;
{ release all locked logical records, doesn't remove them from the table }
BEGIN
WITH Regs DO
BEGIN
AH := $D3;
MsDos(Regs);
Release_Logical_RecSet := (AL = 0);
END;
END; { Release_Logical_RecSet }
FUNCTION Clear_Logical_Rec(VAR RecName : RecLogType) : Boolean;
{ This call unlocks and removes the Logical Record lock from the table }
BEGIN
WITH Regs DO
BEGIN
AH := $D4;
DS := Seg(RecName);
DX := Ofs(RecName);
MsDos(Regs);
Clear_Logical_Rec := (AL = 0);
END;
END; { Clear_Logical_Rec }
FUNCTION Clear_Logical_RecSet : Boolean;
{ Unlocks and removes from the table all of the stations logical record locks }
BEGIN
WITH Regs DO
BEGIN
AH := $D5;
MsDos(Regs);
Clear_Logical_RecSet := (AL = 0);
END;
END; { Clear_Logical_RecSet }
(* THE FOLLOWING ARE PHYSICAL RECORD LOCK CALLS *)
function Log_Phys_Rec(flg : byte; Handle,Start_Hi,Start_Lo,TimeOut,Size_Hi,Size_Lo : integer): boolean;
{ Flg = bit 0 set means log and lock, bit 1 set means non-exclusive lock }
{ Handle is the file handle, Start is the high and low starting word to lock }
{ from; Size is the high and low word length to lock to. Timeout is in }
{ 1/18th seconds and is only valid if bit 0 of flg is set. }
begin
with regs do
begin
AH := $BC;
AL := flg;
BX := Handle;
CX := Start_hi;
DX := Start_Lo;
BP := TimeOut;
SI := Size_Hi;
DI := Size_Lo;
MSDOS(Regs);
Log_Phys_Rec := (AL = 0); { $FF = fail, $96 = No dynamic memory }
end; { with }
end; { function Log_Phys_Rec(flg : byte; Handle,Start_Hi,Start_Lo,TimeOut,Size_Hi,Size_Lo : integer) }
function Release_Phys_Rec( Handle, Start_Hi, Start_Lo : integer) : boolean;
{ When a record is released, it is unlocked for use by someone else, but }
{ it remains in the log table }
{ Handle is the file handle, Start_Hi and Start_Lo are the boundaries of }
{ the locked region to be released }
begin
with regs do
begin
AH := $BD;
BX := Handle;
CX := Start_Hi;
DX := Start_Lo;
MSDOS(Regs);
Release_Phys_Rec := (AL = 0); { $FF = invalid record }
end;
end; { function Release_Phys_Rec }
function Clear_Phys_Rec(Handle, Start_Hi, Start_Lo : integer): boolean;
{ Handle is the file handle, Start_Hi and Start_Lo are the boundaries }
{ of the file region to be locked. Clearing a record will unlock it }
{ and remove it from the log table. }
begin
with regs do
begin
AH := $BE;
BX := Handle;
CX := Start_Hi;
DX := Start_Lo;
MSDOS(Regs);
Clear_Phys_Rec := (AL = 0);
end;
end; { function Clear_Phys_Rec(Handle, Start_Hi, Start_Lo : integer) }
function Lock_Phys_Rec_Set(flgs : byte; Timeout : integer): boolean;
{ flgs are the lock flags: bit 1 set means shared (non-exclusive) lock }
{ Timeout is in 1/18 seconds, 0 = no wait, -1 means indefinite wait }
{ This function attempts to lock all of the records logged in the station's }
{ log table. }
begin
with regs do
begin
AH := $C2;
AL := flgs;
BP := TimeOut;
MSDOS(Regs);
Lock_Phys_Rec_Set := (AL = 0); { $FF = fail, $FE = timeout fail }
end;
end; { function Lock_Phys_Rec_Set(flgs, Timeout : byte) }
function Release_Phys_Rec_Set : boolean;
{ unlocks the entire record log table of the station. records remain in }
{ the log table. }
begin
regs.AH := $C3;
MSDOS(Regs);
Release_Phys_Rec_Set := (regs.AL = 0);
end; { function Release_Phys_Rec_Set }
function Clear_Phys_Rec_Set : boolean;
{ unlocks and removes from the log table any records logged and locked }
begin
regs.AH := $C4;
MSDOS(Regs);
Clear_Phys_Rec_Set := (regs.AL = 0);
end; { function Clear_Phys_Rec_Set }
{ Note: Example programs and printing functions will be included in the }
{ first revision of this toolbox. }